/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ChateoController;

import ChateoFacadeNI.FacadeNI;
import java.io.File;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import ourMessage.ConnexionUDPClient;
import ourMessage.Hello;
import ourMessage.Text;

/**
 * FXML Controller class
 *
 * @author Samanthol
 */
public class ChatViewController implements Initializable {

    @FXML
    private ListView<User> userList;
    @FXML
    private TextArea messagePanel;
    @FXML
    private TextArea historicTextArea;
    @FXML
    private VBox mainView;
    @FXML
    private VBox connectionView;
    @FXML
    private TextField login;
    @FXML
    private Button connect;
    @FXML
    private Button disconnect;
    @FXML
    private VBox root;
    @FXML
    private Label hiLabel;
    @FXML
    private TextArea writeMsgBox;
    @FXML
    private Button sendMsg;
    @FXML
    private Button sendFile;

    //The list of user where each user is defined by an id you can find in its own class
    private ObservableList<User> allUsers = FXCollections.observableArrayList();
    //The debugging state will provide some more verbose
    private static boolean debug = true;
    //Login of the local user
    private String myLogin = "toto";

    private User localUser;

    //IDs for a user
    InetAddress addr;
    String username;

    //Facades
    private FacadeNI facadeni;
    //Port : STATIC 
    private static int port = 2014;

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {

        try {
            facadeni = new FacadeNI(this, port);
            allUsers = userList.getItems();
            userList.getItems().setAll(allUsers);

            //connection
            setOnConnection();
            //when a user is selected
            setOnUserSelected();
            //when the user clicks on the send message button
            setOnMessageToSend();

            //file
            setOnFileToSend();

            //show the login page
            showLoginPage();

            //disconnection
            setOnDisonnection();

        } catch (SocketException ex) {
            Logger.getLogger(ChatViewController.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void sendAck(String login, InetAddress IPaddr) throws UnknownHostException, SocketException {
        // 
        //-Lancer la methode de la facade qui envoie le ACK
        facadeni.outgoingAck(IPaddr, login);
        //
    }
    /* @pa
     * 
     * 
     */

    public String newUser(String remoteLogin, InetAddress remoteAddr) throws UnknownHostException {
        String out = "";
        User theNewOne = new User(remoteAddr, remoteLogin);

        //We check if the user doesn't already exist in our user list.
        //Ne pas créer un user tant qu'on n'a pas vérifié s'il existe ou pas
        if (!allUsers.contains(theNewOne)) {
            allUsers.add(theNewOne);
        }

        try {
            //userList.add(theNewOne.getId(),theNewOne);
            //Send the ACK to the user that just got connected with our ID
            sendAck(myLogin, InetAddress.getByName("255.255.255.255"));
        } catch (SocketException ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        }
        //GUI Update
        // TODO WHEN THE GUI WILL BE READY
        //

        return out;

    }

    public String newUserAck(String remoteLogin, InetAddress remoteAddr) throws UnknownHostException {
        return newUser(remoteLogin, remoteAddr);

    }

    /**
     * This method is aimed at enabling to connect a localUser.
     *
     * @throws java.net.SocketException
     * @throws java.net.UnknownHostException
     */
    public void connect() throws NullPointerException, SocketException, UnknownHostException {
        try {
            facadeni.outgoingHello(InetAddress.getByName("255.255.255.255"), myLogin);
            System.out.println("The user " + myLogin + " has been connected \n");
        } catch (SocketException se) {
            System.out.println("Error in creation");
        }

    }

    /**
     * This method is aimed at enabling to disconnect a localUser.
     *
     * @throws java.net.UnknownHostException
     * @throws java.net.SocketException
     */
    public void disconnect() throws UnknownHostException, SocketException {
        facadeni.outgoingBye(InetAddress.getByName("255.255.255.255"), myLogin);
        System.out.println("Disconnection of the user " + myLogin);
        
    }

    public String getMyLogin() {
        return myLogin;
    }

    public static boolean DebugMode() {
        return debug;
    }

    //public String userLeft(String login, InetAddress IPaddr){
    public boolean userLeft(String login) {
        User left = null;
        for (User u : allUsers) {
            if (u.getLogin().equals(login)) {
                left = u;
            }
        }
        if (left != null) {
            allUsers.remove(left);
        }
        return true;

    }

    private void showLoginPage() {
        root.getChildren().setAll(connectionView);

    }

    private void showMainView() {
        try {
            root.getChildren().setAll(mainView);
            hiLabel.setText("Hola " + myLogin + "!");
            //to be deleted
            User user = new User(InetAddress.getLocalHost(), "Test");
            user.addMessage(new ChatMessage("Hi you", user, user));

            allUsers.add(user);

        } catch (UnknownHostException ex) {
            Logger.getLogger(ChatViewController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void onUserSelected(User selectedUser) {
        //display the user message
        String display = "";
        for (ChatMessage msg : selectedUser.getMessages()) {
            display += msg + "\n";
        }
        messagePanel.setText(display);
        System.out.println(display);

    }

    private void sendMsg(String msg, User dest) throws SocketException {

            //TODO : send message

    }

    private void setOnConnection() {
        connect.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent t) {
                try {
                    myLogin = login.getText();
                    localUser = new User(InetAddress.getLocalHost(), myLogin);
                    connect();
                    showMainView();
                } catch (UnknownHostException ex) {
                    Logger.getLogger(ChatViewController.class.getName()).log(Level.SEVERE, null, ex);
                } catch (SocketException ex) {
                    Logger.getLogger(ChatViewController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    private void setOnDisonnection() {
        disconnect.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                try {
                    disconnect();
                    showLoginPage();
                    
                    //A REVOIR
                    facadeni.getUDPServer().interrupt();
                    System.exit(0);
                } catch (UnknownHostException ex) {
                    Logger.getLogger(ChatViewController.class.getName()).log(Level.SEVERE, null, ex);
                } catch (SocketException ex) {
                    Logger.getLogger(ChatViewController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        
        
    }

    private void setOnUserSelected() {
        userList.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<User>() {

            @Override
            public void changed(ObservableValue<? extends User> ov, User t, User t1) {
                onUserSelected(userList.getSelectionModel().getSelectedItem());
            }

        });
    }

    public void onExit() {
        facadeni.getUDPServer().interrupt();
    }

    private void setOnMessageToSend() {
        sendMsg.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent t) {
                try {
                    User dest = userList.getSelectionModel().getSelectedItem();
                    sendMsg(writeMsgBox.getText(), dest);
                    ChatMessage msg = new ChatMessage(writeMsgBox.getText(), localUser, dest);
                    messagePanel.appendText(msg.toString() + "\n");
                    writeMsgBox.setText("");
                } catch (SocketException ex) {
                    Logger.getLogger(ChatViewController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    private void sendFile(File selectedFile, User dest) {
        //TODO : send the file
    }

    private void setOnFileToSend() {
        sendFile.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent t) {
                FileChooser chooser = new FileChooser();
                File selectedFile = chooser.showOpenDialog(null);
                if (selectedFile != null) {
                    sendFile(selectedFile, userList.getSelectionModel().getSelectedItem());
                }
            }

        });
    }

}
